import type { ComponentInternalInstance, Slots, VNode } from 'vue';
import { h } from 'vue';
import { camelCase } from 'lodash-es';

interface JSXRenderContext {
  defaultNode?: VNode | string;
  params?: Record<string, any>;
}

/**
 * 渲染 TNode，props 和插槽同时处理。与 renderTNodeJSX 区别在于 属性值为 undefined 时会渲染默认节点
 */
export const renderTNode = (instance: ComponentInternalInstance | null, name: string, options?: Slots | JSXRenderContext): any => {
  if (instance === null) {
    return h('', null);
  }

  const params = typeof options === 'object' && 'params' in options ? options.params : null;
  const defaultNode = typeof options === 'object' && 'defaultNode' in options ? options.defaultNode : options;

  let propsNode: any;
  if (name in instance.props || camelCase(name) in instance.props) {
    propsNode = instance.props[name] || instance.props[camelCase(name)];
  }

  if (instance.slots[name]) {
    return instance.slots[name]?.call(params);
  }

  if (typeof propsNode === 'function') return propsNode(h, params);

  const isPropsEmpty = [undefined, params, ''].includes(propsNode);

  if (isPropsEmpty && instance.slots[name]) return instance.slots[name]?.call(params);

  if (!propsNode && defaultNode) {
    return defaultNode;
  }
  return propsNode;
};

/**
 * 用于处理相同名称的 TNode 渲染
 */
export const renderContent = (instance: ComponentInternalInstance | null, name1: string, name2: string, options?: VNode | JSXRenderContext): any => {
  if (instance === null) {
    return h('', null);
  }
  const params = typeof options === 'object' && 'params' in options ? options.params : null;
  const defaultNode = typeof options === 'object' && 'defaultNode' in options ? options.defaultNode : options;
  const toParams = params ? { params } : undefined;
  const node1 = renderTNode(instance, name1, toParams);
  const node2 = renderTNode(instance, name2, toParams);
  const r = [undefined, null, ''].includes(node1) ? node2 : node1;
  return [undefined, null, ''].includes(r) ? defaultNode : r;
};
